#!/usr/bin/env ruby
# By atmos@atmos.org
# this goes in your script/ directory
# it parses your memcached.yml file and hooks you up w/ some info
# it keeps you from having to mess w/ stale memcached daemons for whatever reason.
require 'yaml'
require 'timeout'
require 'erb'

class MemcachedCtl
  attr_accessor :memcached, :memory, :pids, :servers, :ip_address, :ethernet_device

  def initialize
    env = ENV['RAILS_ENV'] || 'development'
    self.memcached = `which memcached`.chomp
    self.servers = [ ]
    self.pids    = { }
    self.ethernet_device = ENV['ETH'] || 'eth0'
    self.ip_address = get_ip_address || '0.0.0.0'
    self.memory = '128'
    
    config = YAML.load(ERB.new(IO.read((File.expand_path(File.dirname(__FILE__) + "/../config/memcached.yml")))).result)
    self.servers = [ config['defaults']['servers'] ].flatten rescue ['127.0.0.1:11211']
    self.servers = [ config[env]['servers'] ].flatten if config[env]['servers']
    self.servers.reject! { |server| host,port = server.split(/:/); self.ip_address == host }
    self.memory = config[env]['memory'] unless config[env]['memory'].nil?
    
    each_server do |host,port|
      `ps auwwx | grep memcached | grep '\\-l #{ip_address} \\-p #{port}' | grep -v grep`.split(/\n/).each do |line|
        self.pids[port] = line.split(/\s+/)[1]
      end
      self.pids[port] ||= 'Down'
    end
  end
  
  def execute(cmd)
    send(cmd) rescue usage
  end
  
  def restart; stop; sleep 1; start end
  
  def status
    each_server { |host,port| puts "Port #{port} -> #{pids[port] =~ /\d+/ ? 'Up' : 'Down'}" }
  end
  
  def kill
    each_server { |host,port| `kill -9 #{pids[port]} > /dev/null 2>&1` if pids[port] =~ /\d+/ }
  end
  
  def stop; kill end
  
  def start
    each_server do |host,port|
      `#{memcached} -d -m #{memory} -l #{ip_address} -p #{port}`
      STDERR.puts "Try memcached_ctl status" unless $? == 0
    end
  end

  def usage
    methods = %w[start stop restart kill status]
    puts "Usage: script/memcached_ctl [ " + (methods * ' | ') + " ]"
  end
    
protected
  def each_server
    servers.each do |server|
      host, port = server.split(/:/)
      yield host, port
    end
  end
  
  def get_ip_address # this works on linux you might have to tweak this on other oses
    line = `/sbin/ifconfig #{ethernet_device} | grep inet | grep -v inet6`.chomp
    if line =~ /\s*inet addr:((\d+\.){3}\d+)\s+.*/
      self.ip_address = $1
    end
  end
end
###########################################################################

MemcachedCtl.new.execute(ARGV.first)
